#include <fstream>
#include "conv.h"
#include "deconv.h"
#include "im2col.h"
#include "utils.h"
#include "unet_v1_q_params.h"
#include "unetv1.h"
#include "concat.h"
#include "norm_actv.h"
#include "maxPool.h"
#include "add_bias.h"

template<
    unsigned W,
    unsigned B,
    unsigned QRS,
    unsigned PICH, 
    unsigned POCH, 
    unsigned PCH,
    unsigned NIW,
    unsigned NICH,
    unsigned NIH,
    unsigned NOH,
    unsigned NOW,
    unsigned NOCH
>
void conv_kernel(data_stream<CONV_A_BIT>& in, axiu_stream<CONV_A_BIT>& out)
{
    #pragma HLS INTERFACE axis register both port=in
    #pragma HLS INTERFACE axis register both port=out
	#pragma HLS INTERFACE ap_ctrl_none port=return

	#pragma HLS DATAFLOW  
    std::cout << "conv1-1" << std::endl;
    data_stream<PICH * CONV_A_BIT> s_conv_im2col_in("s_conv_im2col_in");
    data_stream<PICH * CONV_A_BIT> s_conv_im2col("s_conv_im2col");
    data_stream<POCH * CONV_B_BIT> s_conv("s_conv");
    data_stream<PCH * CONV_B_BIT> s_conv_actv_in("s_conv_actv_in");
    data_stream<PCH * CONV_A_BIT> s_conv_actv("s_conv_actv");
    #pragma HLS STREAM variable=s_conv_im2col_in         depth=CONV_KH*NIW*NICH/PICH dim=1
    #pragma HLS STREAM variable=s_conv_im2col            depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_conv                   depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_conv_actv_in           depth=DEFAULT_DEPTH dim=1
    #pragma HLS STREAM variable=s_conv_actv              depth=DEFAULT_DEPTH dim=1

    #pragma HLS RESOURCE variable=s_conv_im2col_in       core=FIFO_BRAM
    #pragma HLS RESOURCE variable=s_conv_im2col          core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_conv                 core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_conv_actv_in         core=FIFO_SRL
    #pragma HLS RESOURCE variable=s_conv_actv            core=FIFO_SRL

    expandWidth<CONV_A_BIT, PICH * CONV_A_BIT, NIH * NIW * NICH>(
        in, s_conv_im2col_in);
    im2col_3x3<1, NIH, NIW, NICH*CONV_A_BIT, PICH*CONV_A_BIT, 0>(s_conv_im2col_in, s_conv_im2col);
    conv<PICH, POCH,NICH, NOCH,
         CONV_KH, CONV_A_BIT, CONV_W_BIT, CONV_B_BIT,
         NOH * NOW>(s_im2col, s_conv1_1, W);

    reduceWidth<POCH * CONV_B_BIT, PCH * CONV_B_BIT,
                NOH * NOW * NOCH / POCH>(s_conv1_1,
                                                    s_actv_in);
    norm_actv<PCH, NOCH, CONV_B_BIT, CONV_M_BIT, CONV_A_BIT,
              NOH * NOW>(s_actv_in, s_actv, B, QRS);
    //激活
    data_stream<CONV_A_BIT> s_data_out("s_data_out");
    #pragma HLS STREAM variable=s_data_out      depth=DEFAULT_DEPTH dim=1
    #pragma HLS RESOURCE variable=s_data_out    core=FIFO_SRL
    reduceWidth<PCH * CONV_A_BIT, CONV_A_BIT,
                NOH * NOW * NOCH / PCH>(s_actv, s_data_out);

    add_last<CONV_A_BIT, NOH * NOW * NOCH>(s_data_out, out);
    return ;

}